#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    Algoritmo de Cifrado/Descifrado en flujo A5/1
    Copyright (C) 2012 Darío López Padial y César Aguilera 
    @bukosabino
    @Cs4r
    ‏
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>
"""

################################################################################
#
#   Ejecución: python a51.py <semillas.txt> <numero_bits>
#
#   Objetivo: Dado un archivo con la clave (semilla) en forma triple secuencia
#				y un número de bits, compone un generador de secuencias A5/1
#				que genera un archivo llamado secuencia.txt con tantos bits 
#				como se indican por parámetro.
#
#				Los polinomios de conexión de los tres LFSR que utiliza este
#				generador son:
#					D1(X) = X^19 + X^18 + X^17^+ X^14 + 1
#					D2(X) = X^22 + X^21 + 1
#					D3(X) = X^23 + X^22 + X^21 + X^8 + 1
#				
################################################################################
import sys
f = open(sys.argv[1], "r")
semilla = []
for linea in f.readlines():
	semilla.append([int(i) for i in list(linea) if i.isdigit() ])
f.close()
polinomio = [[1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
				[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
				[1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0]
			 ]
bit_control = [10,11,12]

def mayoria():
    if semilla[0][bit_control[0]] == semilla[1][bit_control[1]]:
        return semilla[0][bit_control[0]] # 000, 001, 110, 111
    else:
        return semilla[2][bit_control[2]] # 010, 011, 100, 101
        
secuencia = []

num_bits = int(sys.argv[2])
while len(secuencia) < num_bits:
	
	bit_saliente = (semilla[0][0] + semilla[1][0] + semilla[2][0]) % 2
	secuencia.append(bit_saliente)
	
	predominante = mayoria()
	for i in range(3):
		if semilla[i][bit_control[i]] == predominante :
			nuevo_bit = 0			
			for j in range(len(polinomio[i])):
				if polinomio[i][j] == 1:
					nuevo_bit += semilla[i][j]
			
			nuevo_bit = nuevo_bit % 2
#			semilla[i] = semilla[i][1:] + [nuevo_bit] # Actualiza la semilla u
			semilla[i].pop(0)
			semilla[i].append(nuevo_bit)

f = open("secuencia.txt","w")
f.write("".join(map(lambda x: str(x), secuencia)))
f.close()
